#ifndef ___fuse_getattr
#define ___fuse_getattr 1

#ifndef FUSE_USE_VERSION
#define FUSE_USE_VERSION 28
#endif

#include <stdio.h>
#include <stdlib.h>
#include "mtlib.c"
#include <fuse.h>
#include <fcntl.h>
#include <errno.h>
#include "logging.c"

struct datosAtributos {
    struct stat * ptr;
    char * path;
    char estado;
};

//PROTOTIPOS
int fuse_getattr(const char *, struct stat *);
void ___fuse_procesar_mensaje_getattr(unsigned char, mti_mensaje, struct datosAtributos *);

//OBTENER ATRIBUTOS
int fuse_getattr(const char * path, struct stat * pNue) {     //obtengo los atributos de un archivo,,
//recibo un puntero a una estructura stat con contiene los campos de los atributos del archivo.

    int resultado;
    mti_mensaje datosMensaje;
    unsigned char centro_getattr = 0;
    unsigned int descriptorConexion;
    struct datosAtributos datos;

        datos.estado = 0;
        datos.ptr = pNue;
        datos.path = path;

        while (centro_getattr == 0)

        centro_getattr = mtf_obtener_descriptor(1024);

        descriptorConexion = mtf_conectar(centro_getattr, MTP_INTERNO, centro_fat);

            if (descriptorConexion == 0) {
                mtf_liberar_descriptor(centro_getattr); //libero centro de mensajes con sus datos y conexiones
                return -EAGAIN;

            } else

                resultado = mtf_enviar_mensaje(centro_getattr, descriptorConexion, MTE_OBTENER_ATRIBUTOS, (char *) datos.path);

                if (resultado == 0) {
                    mtf_desconectar(centro_getattr,descriptorConexion); //desconecto la conexion del centro de mensajes
                    mtf_liberar_descriptor(centro_getattr); //libero centro de mensajes con sus datos y conexiones
                    return -EAGAIN;

                } else {

                    while (! (datos.estado)) {

                        while(! (mtf_recibir_mensajes(centro_getattr)));

                    datosMensaje = mtf_siguiente_mensaje(centro_getattr);
                    ___fuse_procesar_mensaje_getattr(centro_getattr, datosMensaje, &datos);
                    mtf_descartar_mensaje(centro_getattr, datosMensaje.codigo);
                    }

                }
                    mtf_desconectar(centro_getattr,descriptorConexion); //desconecto la conexion del centro de mensajes
                    mtf_liberar_descriptor(centro_getattr); //libero centro de mensajes con sus datos y conexiones

                    switch (datos.estado) {

                    case 1:
                        return -ENOENT; //path no existe
                    default:
                        return EXIT_SUCCESS;
                    }

}

void ___fuse_procesar_mensaje_getattr(unsigned char centro_getattr, mti_mensaje datosMensaje, struct datosAtributos * datosSetAtributos) {

      if (datosMensaje.categoria != MTA_MENSAJE) return;

            switch (datosMensaje.tipo) {

                case MTE_NULL:

                  mtf_enviar_mensaje(centro_getattr, datosMensaje.remitente, MTR_NULL);

                break;

                case MTR_NULL: case MTQ_MENSAJE_NO_VALIDO:

                break;

                //MENSAJES PARA OBTENER ATRIBUTOS
                case MTR_ATRIBUTOS:
                {

                    long horaCreacion, tamano, hardlinks, bloques;
                    short fechaCreacion;
                    char modificado, soloLectura;
                    char * nombreArchivo = NULL;

                    memset(datosSetAtributos -> ptr, 0 , sizeof(datosSetAtributos -> ptr)); //borro la estructura stat,, la lleno con 0

                    mtf_obtener_datos(centro_getattr, datosMensaje.codigo,(char **) &nombreArchivo,(long int *)
                                        &tamano,(long int *) &hardlinks, (char *) &soloLectura, (char *) &modificado,(short int *)
                                        &fechaCreacion, (long int *) &horaCreacion);

                    fechaCreacion = 0; //no la voy a utilizar
                    horaCreacion = 0;  //idema arriba

                    datosSetAtributos -> ptr -> st_nlink = hardlinks; //cant de hardlinks(referencias a archivos)

                    //completo los atributos de la estructura stat
                    
                        //asigno permisos
                        if (soloLectura == 0) {
                            datosSetAtributos -> ptr -> st_mode = S_IFREG | 0777; //acceso total en modo octal

                        } else
                            datosSetAtributos -> ptr -> st_mode = S_IFREG | 0555; //lectura y ejecucion en modo octal

                        if (hardlinks > 1) { //es un directorio
                                datosSetAtributos -> ptr -> st_mode = datosSetAtributos -> ptr -> st_mode + S_IFDIR;
                                
                        } else
                                datosSetAtributos -> ptr -> st_mode = datosSetAtributos -> ptr -> st_mode + S_IFREG;
                            
                    datosSetAtributos -> ptr -> st_size = tamano; //tamano del archivo

                    datosSetAtributos -> ptr -> st_blksize = 4096; //tamano del bloque del file system

                    bloques = ((tamano - 1) / 4096 ) + 1;   
                    datosSetAtributos -> ptr -> st_blocks = bloques; //bloques asignados al archivo

                    log_registrar(descArch, "FUSE", LOG_INFO, "Atributos obtenidos %s \n", nombreArchivo);
                    free(nombreArchivo);
            }
            break;

            case MTR_NO_OBTUVO_ATRIBUTOS:
            {
                char * nombreArchivo = NULL;
                char motivo;

                    mtf_obtener_datos(centro_getattr, datosMensaje.codigo,(char **) &nombreArchivo,(char *) &motivo);

                    datosSetAtributos -> estado = motivo;
                    log_registrar(descArch, "FUSE", LOG_WARN, "No se obtuvieron atributos %s \n", nombreArchivo);
                    free(nombreArchivo);

                break;
            }

            default:

              mtf_enviar_mensaje(centro_getattr, datosMensaje.remitente, MTQ_MENSAJE_NO_VALIDO);

            break;

        }
}

#endif

